package org.anderground.modules.editor.tools.geocoding;

import geo.google.GeoAddressStandardizer;
import geo.google.GeoException;
import geo.google.datamodel.GeoAddress;
import geo.google.datamodel.GeoStatusCode;

import java.util.HashMap;
import java.util.List;

import org.anderground.core.Logger;
import org.anderground.core.model.Editor;
import org.anderground.core.model.ModelData;
import org.anderground.core.model.Station;
import org.anderground.core.model.Tunnel;
import org.anderground.core.util.Coord;
import org.anderground.modules.editor.tools.EditorTool;

/**
 * @author Ilya Shurigyn
 */
public class GoogleGeocodingTool implements EditorTool {

	private static Geowindow geowindow;

	public GoogleGeocodingTool() {
	}

	@Override
	public void call(ModelData data, Station[] selectedStations,
			Tunnel[] selectedTunnels) {
		geowindow = new Geowindow(data);
		geowindow.setVisible(true);
		// GoogleGeocoding.fetchAllStationCoords(EditorModel
		// .getInstance().getData());
	}

	@Override
	public String getName() {
		return "Geocoding";
	}

	@Override
	public String[] getConsoleArgs() {
		return new String[]{"g","geocode"};
	}

	@Override
	public void callInConsole(ModelData data, String arg, String[] subargs) {
		HashMap<Station,GeoAddress[]> map = new HashMap<Station, GeoAddress[]>(); 
		GeoAddressStandardizer standardizer = new GeoAddressStandardizer(
				GoogleAPIDeveloperData.API_KEY, 1000);
		String request;
		int stationCount = data.getStations().size();
		int fetchedStationCount = 0;
		System.out.print("\n");
		try {
			for (Station station : data.getStations()) {
				Logger.d("fetching " + station);
				request = Geowindow.getRequestForStation(data, station);
				List<GeoAddress> geoAddresses = null;
				System.out.write(13);
				System.out.print("[");
				for(int i=0;i<100;i++) {
					if(i<=(fetchedStationCount/stationCount)*100) {
						System.out.print("|");
					} else {
						System.out.print(" ");
					}
						
				}
				System.out.print("]" + ((fetchedStationCount/stationCount)*100) + "%");
				try {
					geoAddresses = standardizer
							.standardizeToGeoAddresses(request);
				} catch (geo.google.GeoException e) {
					if (e.getStatus() == GeoStatusCode.G_GEO_UNKNOWN_ADDRESS) {
						System.out.println("cannot find address:" + request);
						
					} else
						throw e;
				} finally {
					map.put(station, (geoAddresses == null) ? null
							: geoAddresses.toArray(new GeoAddress[0]));
					
				}
				
			}

		} catch (GeoException e) {
			// GeoStatusCode.G_GEO_UNKOWN_STATUS - sleep interupted(on
			// window cancel)
			if (e.getStatus() != GeoStatusCode.G_GEO_UNKOWN_STATUS) {
				e.printStackTrace();
			}
		}
		for (Station st: map.keySet()) {
			if(map.get(st)!=null)
			new Editor() {
				public void setCoord(Station station, GeoAddress address) {
					if (address != null) {
						getEditor(station)
								.setLocation(
										new Coord(
												(int) (address.getCoordinate()
														.getLatitude() * 1e6),
												(int) (address.getCoordinate()
														.getLongitude() * 1e6)));
					}
				}
			}.setCoord(st, map.get(st)[0]);

		}
	}

}
